from flask_sqlalchemy import SQLAlchemy
from uuid import uuid4
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin

from app import db

def generate_uuid():
    return str(uuid4())

# 用户表
class User(db.Model, UserMixin):
    __tablename__ = 'users'

    id = db.Column(db.String(36), primary_key=True, default=generate_uuid)
    username = db.Column(db.String(50), unique=True, nullable=False)
    email = db.Column(db.String(100), unique=True, nullable=False)
    password_hash = db.Column(db.String(255), nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

    roles = db.relationship('Role', backref='user', lazy=True, cascade='all, delete-orphan')
    conversations = db.relationship('Conversation', backref='user', lazy=True, cascade='all, delete-orphan')
    settings = db.relationship('UserSettings', backref='user', uselist=False, cascade='all, delete-orphan')

# 角色表
class Role(db.Model):
    __tablename__ = 'roles'

    id = db.Column(db.String(36), primary_key=True, default=generate_uuid)
    user_id = db.Column(db.String(36), db.ForeignKey('users.id'), nullable=False)
    name = db.Column(db.String(100), nullable=False)
    description = db.Column(db.Text)
    system_prompt = db.Column(db.Text, nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    conversations = db.relationship('Conversation', backref='role', lazy=True, cascade='all, delete-orphan')

# 对话表
class Conversation(db.Model):
    __tablename__ = 'conversations'

    id = db.Column(db.String(36), primary_key=True, default=generate_uuid)
    user_id = db.Column(db.String(36), db.ForeignKey('users.id'), nullable=False)
    role_id = db.Column(db.String(36), db.ForeignKey('roles.id'), nullable=False)
    title = db.Column(db.String(100), nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    messages = db.relationship('Message', backref='conversation', lazy='dynamic')

# 消息表
class Message(db.Model):
    __tablename__ = 'messages'

    id = db.Column(db.String(36), primary_key=True, default=generate_uuid)
    conversation_id = db.Column(db.String(36), db.ForeignKey('conversations.id'), nullable=False)
    role = db.Column(db.Enum('system', 'user', 'assistant', name='message_role'), nullable=False)
    content = db.Column(db.Text, nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

# 用户设置表
class UserSettings(db.Model):
    __tablename__ = 'user_settings'

    user_id = db.Column(db.String(36), db.ForeignKey('users.id', ondelete='CASCADE'), primary_key=True, nullable=False)
    max_tokens = db.Column(db.Integer, default=2000)
    temperature = db.Column(db.Float, default=0.7)
    top_p = db.Column(db.Float, default=1.0)
    presence_penalty = db.Column(db.Float, default=0.0)
    frequency_penalty = db.Column(db.Float, default=0.0)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

# 系统角色表
class SystemRoles(db.Model):
    __tablename__ = 'system_roles'

    id = db.Column(db.String(36), primary_key=True, default=generate_uuid)
    name = db.Column(db.String(100), nullable=False)
    description = db.Column(db.Text)
    system_prompt = db.Column(db.Text, nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

# 设备表
class Device(db.Model):
    __tablename__ = 'devices'

    id = db.Column(db.String(36), primary_key=True, default=generate_uuid)
    device_code = db.Column(db.String(50), unique=True, nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    shadow_data = db.relationship('DeviceShadowData', backref='device', lazy='dynamic', cascade='all, delete-orphan')

# 设备影子数据表
class DeviceShadowData(db.Model):
    __tablename__ = 'device_shadow_data'

    id = db.Column(db.String(36), primary_key=True, default=generate_uuid)
    device_id = db.Column(db.String(36), db.ForeignKey('devices.id', ondelete='CASCADE'), nullable=False)
    stat = db.Column(db.Boolean, nullable=True)
    hum = db.Column(db.Float, default=0.0, nullable=True)
    tem = db.Column(db.Float, default=0.0, nullable=True)
    light = db.Column(db.Float, default=0.0, nullable=True)
    soil = db.Column(db.Float, default=0.0, nullable=True)
    rain = db.Column(db.Float, default=0.0, nullable=True)
    uv = db.Column(db.Integer, default=0, nullable=True)
    co2 = db.Column(db.Integer, default=0, nullable=True)
    led = db.Column(db.Boolean, nullable=True)
    fan = db.Column(db.Boolean, nullable=True)
    water = db.Column(db.Boolean, nullable=True)
    timestamp = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)

    __table_args__ = (
        db.Index('idx_device_id_timestamp', 'device_id', 'timestamp'),
    )


class DeviceCommand(db.Model):
    __tablename__ = 'device_commands'

    id = db.Column(db.String(36), primary_key=True, default=generate_uuid)
    device_id = db.Column(db.String(36), db.ForeignKey('devices.id', ondelete='CASCADE'), nullable=False)
    user_id = db.Column(db.String(36), db.ForeignKey('users.id'), nullable=True)  # 发起命令的用户，可为空（AI 触发）
    conversation_id = db.Column(db.String(36), db.ForeignKey('conversations.id'), nullable=True)  # AI 触发的对话ID，可为空
    command_type = db.Column(db.String(50), nullable=False)  # 命令类型，例如 'open_led', 'set_rgb', 'open_fan'
    command_data = db.Column(db.JSON, nullable=False)  # 命令参数，例如 {'led_red': 255, 'led_green': 255, 'led_blue': 255}
    status = db.Column(db.Enum('pending', 'sent', 'completed', 'failed', name='command_status'), default='pending')  # 命令状态
    created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    error_message = db.Column(db.Text, nullable=True)  # 记录失败原因（如果有）

    __table_args__ = (
        db.Index('idx_device_id_created_at', 'device_id', 'created_at'),
    )